<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue2 Gridstack</title>
    <link rel="stylesheet" href="demo.css"/>
    <script src="../dist/gridstack-all.js"></script>
  </head>
  <body>
    <main id="app">
      <h1>How to integrate GridStack.js with Vue.js</h1>
      <p>
        As with any virtual DOM based framework, you need to check if Vue has
        rendered the DOM (or any updates to it) <strong>before</strong> you
        initialize GridStack or call its methods. As a basic example, check this
        component's <code>mounted</code> hook.
      </p>
      <p>
        If your app requires more complex render logic than the inline template
        in `addWidget`, consider
        <a
          href="https://github.com/gridstack/gridstack.js/tree/master/doc#makewidgetel"
          >makeWidget</a
        >
        to let Vue deal with DOM rendering.
      </p>
      <button type="button" @click="addNewWidget()">Add Widget</button> {{ info }}
      <div class="grid-stack"></div>
    </main>
    <script type="module">
      import Vue from "https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js";

      let app = new Vue({
        el: "#app",
        data: {
          // Reference to the GridStack instance to access it later
          grid: undefined,
          count: 0,
          info: "",
          timerId: undefined,
        },
        items: [
          { x: 2, y: 1, h: 2 },
          { x: 2, y: 4, w: 3},
          { x: 4, y: 2},
          { x: 3, y: 1, h: 2 },
          { x: 0, y: 6, w: 2, h: 2 }
        ],
        watch: {
          /**
           * Clear the info text after a two second timeout. Clears previous timeout first.
           */
          info: function (newVal, oldVal) {
            if (newVal.length === 0) return;

            window.clearTimeout(this.timerId);
            this.timerId = window.setTimeout(() => {
              this.info = "";
            }, 2000);
          },
        },
        mounted: function () {
          // Provides access to the GridStack instance across the Vue component.
          this.grid = GridStack.init({ float: true, cellHeight: '70px', minRow: 1 });

          // Use an arrow function so that `this` is bound to the Vue instance. Alternatively, use a custom Vue directive on the `.grid-stack` container element: https://vuejs.org/v2/guide/custom-directive.html
          this.grid.on("dragstop", (event, element) => {
            const node = element.gridstackNode;
            // `this` will only access your Vue instance if you used an arrow function, otherwise `this` binds to window scope. see https://hacks.mozilla.org/2015/06/es6-in-depth-arrow-functions/
            this.info = `you just dragged node #${node.id} to ${node.x},${node.y} – good job!`;
          });
        },
        methods: {
          addNewWidget: function () {
            const node = this.$options.items[this.count] || {
              x: Math.round(12 * Math.random()),
              y: Math.round(5 * Math.random()),
              w: Math.round(1 + 3 * Math.random()),
              h: Math.round(1 + 3 * Math.random()),
            };
            node.id = node.content = String(this.count++);
            this.grid.addWidget(node);
          },
        },
      });
    </script>
  </body>
</html>
